#pragma once
#include <string>
#include <list>
#include <string.h>
namespace axis {
class Servo;
class CommuPort
{
public:
    CommuPort()
    {
        memset(&tx_data_, 0, sizeof(tx_data_));
        memset(&rx_data_, 0, sizeof(rx_data_));
        memset(&last_rx_data, 0, sizeof(last_rx_data));
        ecode_stack_.clear();
    }
    struct TxData
    {
        uint16_t ctrlword;
        int32_t target_pos;
        int16_t target_torq;
        uint8_t opmode;
        uint8_t led;
    };
    struct ErrCode
    {
        uint64_t timestamp;
        uint32_t ecode;
        uint8_t category;  //错误类型：0-  1-  2-
    };
    struct RxData
    {
        uint16_t statusword;
        int32_t actual_pos;
        int16_t actual_torq;
        uint8_t opmode_display;
        uint8_t collision_lv;
        bool backdrive_stat;
        uint16_t ota_pos_diff;           // 通道1  ch6-位置误差
        uint16_t ota_dual_encoder_diff;  // 通道2  ch15-双编码器差值
        uint16_t ota_dc_vol;             // 通道3  ch90-关节母线电压
        ErrCode error;
        bool has_ext_enable_bit;  //对于can通讯类型的伺服，需要外部额外的标记来表示使能状态
    };

    inline const TxData& tx() { return tx_data_; }
    inline const RxData& rx() { return rx_data_; }
    inline RxData& set_rx() { return rx_data_; }
    inline void push_error(uint16_t errcode, uint8_t errtype)
    {
        if (errcode != rx_data_.error.ecode)
        {
            rx_data_.error.ecode = errcode;
            rx_data_.error.category = errtype;
            rx_data_.error.timestamp = 0;
            // AXIS_DEBUG("servo %d report error 0x%x category:%d", get_id(), e.ecode, e.category);
        }
    }

private:
    TxData tx_data_;
    RxData rx_data_, last_rx_data;
    std::list<ErrCode> ecode_stack_;  //错误历史

    friend class axis::Servo;
};
}  // namespace axis
